package zzps.exeed.kernel.aop.asm;

import zzps.exeed.kernel.aop.ProxyFactory;
import zzps.exeed.kernel.holder.PandaHolder;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class AsmProxyFactory implements ProxyFactory {

    // 缓存容器，防止生成同一个Class文件在同一个ClassLoader加载崩溃的问题
    private static final Map<String, Class<?>> proxyClassCache = new HashMap<>();
    private static final AsmClassLoader asmClassLoader = new AsmClassLoader(AsmProxyFactory.class.getClassLoader());
    @Override
    public <T> T createProxy(PandaHolder<T> pandaHolder, InvocationHandler invocationHandler) throws Exception {
        String name = pandaHolder.clazz().getName();
        Class<?> proxyClass = proxyClassCache.get(pandaHolder.clazz().getName());
        if (proxyClass == null){
            proxyClass = AsmClassCreator.createClass(pandaHolder.clazz(), asmClassLoader, pandaHolder);
            proxyClassCache.put(name,proxyClass);
        }
        Constructor<?> constructor = proxyClass.getConstructor();
        Object instance = constructor.newInstance();
        Method  setInvocationHandler = proxyClass.getDeclaredMethod(AsmClassCreator.set_invocationhandler_method, InvocationHandler.class);
        Method setOverwriteMethod = proxyClass.getDeclaredMethod(AsmClassCreator.set_overwrite_method, PandaHolder.class);
        setInvocationHandler.setAccessible(true);
        setInvocationHandler.invoke(instance,invocationHandler);
        setOverwriteMethod.setAccessible(true);
        setOverwriteMethod.invoke(instance,pandaHolder);
        return (T)instance;
    }
}
